-- Face
	vLast_Auto_Facing = 0.25
-- Loot
	vLast_Loot_Time = 0.25
	vPauseStealth = false
	-- ObjectDescriptor(unit, 0x28, Types.UInt)
	UNIT_DYNAMIC_FLAGS_OFFSET = 0x28
	UNIT_DYNAMIC_FLAG_LOOTABLE = 0x26
	function UnitIsLootable(unit) return bit.band(ObjectDescriptor(unit, UNIT_DYNAMIC_FLAGS_OFFSET, Types.UInt), UNIT_DYNAMIC_FLAG_LOOTABLE) ~= 0 end
	function UnitIsSelectable(unit) return bit.band(ObjectDescriptor(unit, 0x28, Types.UInt), 0x2000000) == 0 end
-- Mana Potion
	vLastManaPotionAttempt = 0.25
-- Skin
	vSkinTime = 0.25
	SKIN_UNIT_FLAGS_OFFSET = 0x16C -- 6.0.3 (19116)
	UNIT_FLAGS_SKINNABLE = 0x4000000
	function UnitIsSkinnable(unit) return bit.band(ObjectDescriptor(unit, SKIN_UNIT_FLAGS_OFFSET, Types.UInt), UNIT_FLAGS_SKINNABLE) ~= 0 end
-- Target
	vLastAutoTarget = 0.25
-- Functions
ccR.Auto = {
	Face =
	function(unit, force)
		if unit == nil then unit = "target" end
		if ccR.Unit.Exists(unit)
		and HasFullControl()
		and ccR.Unit.Is.Attackable(unit)
		and not tContains(ccR.tblIgnoreNPCWithAutoFace, ccR.Unit.NPCID(unit))
		and (
				(	
					force ~= nil
				)
				or
				(
					force == nil
					and not ccR.Player.Is.Channeling()
					and	not ccR.Player.Is.Moving()
					and (GetTime()-vLast_Auto_Facing) > ccR.Var("Auto_Face_Delay")
					and (not ccR.Var("Auto_Face_InCombatOnly") or (ccR.Var("Auto_Face_InCombatOnly") and ccR.Player.Is.InCombat()))
				)
			)
		then
			if ccR.Unit.Exists("player")
			and ccR.Unit.Exists(unit)
			then
				local X1, Y1 = ObjectPosition("player")
				local X2, Y2 = ObjectPosition(unit)
				local Angle = rad(atan2(Y2 - Y1, X2 - X1))
				local IsExactFacing = abs(ObjectFacing("player") - Angle) < 0.1
				if not IsExactFacing then
					local pX, pY = ObjectPosition("player")
					local tX, tY = ObjectPosition(unit)
					FaceDirection(math.atan2(tY - pY, tX - pX) % (math.pi * 2))
					vLast_Auto_Facing = GetTime()
				end
			end
		end
	end,
	Health_Potions =
	function()
		if ccR.Player.Health() <= ccR.Var("Health_Potion_HP")
		and ccR.Player.Is.Alive()
		and ccR.Player.Is.InCombat()
		and HasFullControl()
		and not IsResting()
		then
			local vPotion = nil
			for i = # tbl_Health_Potions, 1, -1 do
				vPotion = tbl_Health_Potions[i]
				-- Convert ItemID to Name
				if tonumber(vPotion) ~= nil then 
					local name, link, quality, iLevel, reqLevel, class, subclass, maxStack, equipSlot, texture, vendorPrice = GetItemInfo(vPotion)
					vPotion = name
				end
				local isUsable = IsUsableItem(vPotion)
				local startTime, duration, enable = GetItemCooldown(tbl_Health_Potions[i])
				-- Check we have a potion, isUsable and not on cooldown
				if GetItemCount(vPotion) > 0 
				and duration == 0
				and isUsable
				then
					UseItemByName(vPotion) 
					ccR.PrintToChat("Health Potion Used: " .. vPotion) 
					break
				end
			end
		end
	end,
	Loot =
	function()
		if GetTime()-vLast_Loot_Time >= 1.5 then
			for Index = 1, ObjectCount() do
				local Object = ObjectWithIndex(Index);
				if bit.band(ObjectType(Object), ObjectTypes.Unit) > 0 then
					if ccR.Unit.Exists(Object)
					and ccR.Unit.Is.Dead(Object)
					and ccR.Unit.Distance(Object, "player") <= 50
					and GetNumLootItems() == 0
					and not ccR.Var("Auto_Loot_Pause")
					and not ccR.Player.Is.CastingOrChanneling()
					and (not ccR.Player.Is.InCombat() or #ccR_Enemies_In_Combat == 0)
					and ((ccR.Var("Auto_Loot_In_Stealth") and ccR.Player.Is.InStealth()) or (not ccR.Player.Is.InStealth()))
					and ((ccR.Var("Auto_Loot_In_Dungeons") or (not ccR.Var("Auto_Loot_In_Dungeons") and ccR.Player.Is.Solo())))
					then
						local hasLoot, canLoot = CanLootUnit(UnitGUID(Object))
						-- Loot-a-Rang
						if ccR.Var("Auto_Loot_Use_LootARang")
						and not ccR.Player.Is.Moving()
						and not IsMounted()
						then
							-- 60854 Engineering 125 Loot-A-Rang
							-- 109167 Findle's Loot-A-Rang
							local Loot_A_Rang 
							if GetItemCount(60854) > 0 then Loot_A_Rang = 60854 end
							if GetItemCount(109167) > 0 then Loot_A_Rang = 109167 end
							if IsUsableItem(Loot_A_Rang)
							and select(2,GetItemCooldown(Loot_A_Rang)) == 0
							and ccR.Unit.Distance(Object, "player") <= 39
							and ccR.Unit.Is.In.LineOfSight(Object, "player")
							and hasLoot and not canLoot
							then
								Loot_A_Rang = GetItemInfo(Loot_A_Rang)
								vLast_Loot_Time = GetTime() + 1.5
								UseItemByName(Loot_A_Rang)
								return
							end
						end

						if ccR.Var("Auto_Loot_Use_Fetch")
						and ccR.Player.Has.Spell(FETCH)
						and not ccR.Player.Is.Moving()
						and not IsMounted()
						then
							if ccR.Pet.IsAlive()
							and ccR.Unit.Distance(Object, "player") <= 49
							and ccR.Unit.Is.In.LineOfSight(Object, "player")
							and hasLoot and not canLoot
							then
								ccR.Cast.Spell(FETCH)
								vLast_Loot_Time = GetTime() + 1.5
							end
						end

						-- Looting corpse nearby player
						if hasLoot and canLoot
						and not ccR.Player.Is.Moving()
						and UnitIsLootable(Object)
						and UnitIsSelectable(Object)
						then
							ccR.Var("Auto_Target_Pause", true)
							vLast_Loot_Time = GetTime()
							vPauseStealth = true
							ObjectInteract(Object)
							return
						else
							ccR.Var("Auto_Target_Pause", false)
							vPauseStealth = false
						end
					else
						vPauseStealth = false
						ccR.Var("Auto_Target_Pause", false)
					end
				end
			end
		end
	end,
	Mana_Potions =
	function()
		if (ccR.Player.Class() == "Druid" and (ccR.Player.Specialization() == 1 or ccR.Player.Specialization() == 4))
		or ccR.Player.Class() == "Mage"
		or ccR.Player.Class() == "Warlock"
		or ccR.Player.Class() == "Priest"
		or ccR.Player.Class() == "Shaman"
		or ccR.Player.Class() == "Paladin"
		or (ccR.Player.Class() == "Monk" and ccR.Player.Specialization() == 2)
		then
			if ccR.Player.Mana() <= ccR.Var("Mana_Potion_MP")
			and ccR.Player.IsAlive()
			and ccR.Player.Is.InCombat()
			and ccR.Target.Exists()
			and not IsResting()	-- Do NOT use mana in towns
			and not tContains(tbl_Training_Dummy, ccR.Unit.NPCID("target"))
			then
				for i = # tbl_Mana_Potions, 1, -1 do
					-- Retrieve potion name/id
					local vTableItem = tbl_Mana_Potions[i]
					local vManaPotion = vTableItem
					-- If it's a ItemID then retrieve it's name
					if tonumber(vTableItem) ~= nil then local name = GetItemInfo(tbl_Mana_Potions[i]) vManaPotion = name end
					-- Check if we actually have one and it's usable, then use it
					local isUsable = IsUsableItem(vManaPotion)
					local startTime, duration, enable = GetItemCooldown(tbl_Mana_Potions[i])
					if GetItemCount(vManaPotion) > 0 
					and duration == 0
					and isUsable
					then
						UseItemByName(vManaPotion) 
						ccR.PrintToChat("Mana Potion Used: " .. vManaPotion) 
						break
					end
				end
			end
		end
	end,
	Open =
	function(Object)
		if ccR.Player.IsAlive()
		and not ccR.Player.IsInCombat()
		and HasFullControl()
		and GetNumLootItems() == 0
		and not ccR.Player.Is.CastingOrChanneling()
		then
			for i = # tbl_AutoOpen, 1, -1 do
				-- Retrieve potion name/id
				local vTableItem = tbl_AutoOpen[i]
				local vItemToOpen = vTableItem
				-- If it's a ItemID then retrieve it's name
				if tonumber(vTableItem) ~= nil then 
					local name = GetItemInfo(tbl_AutoOpen[i]) 
					vItemToOpen = name 
				end
				-- Check if we actually have one and it's usable, then use it
				local isUsable = IsUsableItem(vItemToOpen)
				if GetItemCount(vItemToOpen) > 0 and isUsable then
					UseItemByName(vItemToOpen)
					break
				end
			end
		end
	end,
	Skin =
	function()
		if ccR.Player.Has.Skinning() 
		or ccR.Player.Has.Herbalism()
		or ccR.Player.Has.Mining()
		or ccR.Player.Has.Engineering()
		then
			if GetTime()-vSkinTime >= 1.5 then
				for Index = 1, ObjectCount() do
					local Object = ObjectWithIndex(Index);
					if bit.band(ObjectType(Object), ObjectTypes.Unit) > 0 then
						if ccR.Unit.Exists(Object)
						and ccR.Unit.Is.Dead(Object)
						and ccR.Unit.Distance(Object, "player") <= 50
						and GetNumLootItems() == 0
						and (
								-- Skinning
								-- and UnitIsSkinnable(Object) and tContains(tbl_Auto_Skin, UnitCreatureType(Object)
								(ccR.Player.Has.Skinning() and ccR.Tooltip("word", Object, "Skinnable"))
								or
								-- Herbalism
								-- and not tContains(tbl_Auto_Skin, UnitCreatureType(Object)
								(ccR.Player.Has.Herbalism() and ccR.Tooltip("word", Object, "Requires Herbalism"))
								or
								-- Mining
								(ccR.Player.Has.Mining() and ccR.Tooltip("word", Object, "Requires Mining"))
								or
								-- Engineering
								(ccR.Player.Has.Engineering() and ccR.Tooltip("word", Object, "Requires Engineering"))
							)
						and not ccR.Player.Is.Moving()
						and (not ccR.Player.Is.InCombat() or #ccR_Enemies_In_Combat == 0)
						and not ccR.Player.Is.CastingOrChanneling()
						then
							local hasLoot, canLoot = CanLootUnit(UnitGUID(Object))
							if not hasLoot and canLoot 
							and UnitIsSelectable(Object)
							then
								ObjectInteract(Object)
								vSkinTime = GetTime()
								return
							end
						end
					end
				end
			end
		end
	end,
	Target =
	function()
		if ccR.Target.Exists() 
		and (
				ccR.Sys.IgnoreNPCWithAura("target")
				or ccR.Unit.Is.Immune.To.All("target")
				or ccR.Unit.Is.CC("target")
				or ccR.tblIgnoreNPC[ccR.Unit.NPCID("target")]
				or ccR.tblIgnoreCreatureType[UnitCreatureType("target")] 
			)
		then
			if GetNumLootItems() < 1 then ClearTarget() end
		end

		if ccR.Var("Auto_Target_Pause")
		or vLootTime ~= nil and GetTime()-vLootTime <= 1.5
		or GetTime()-vLastAutoTarget < ccR.Var("Auto_Target_Delay")
		or ccR.Target.GUID() == 76933 -- Prismatic Crystal
		then
			return
		end

		if ccR.Target.Exists()
		and
		(
			ccR.Target.Is.Dead()
			or not UnitCanAttack("player","target")
			or (ccR.Var("Auto_Target_OnlyVisible") and not ccR.Target.Is.VisibleOnScreen())
			or (ccR.Var("Auto_Target_OnlyInfront") and not ccR.Player.Is.Facing("target"))
			or (UnitIsFriend("player", "target") and not UnitCanAttack("player","target"))
			or (UnitReaction("target", "player") >= 4 and not UnitCanAttack("player","target"))
			or (ccR.Var("Auto_Target_Ignore_Pets") and ccR.Unit.Is.APet("target"))
			or ccR.Unit.Distance("target", "player") >= 50
			--or (ccR.Player.Is.In.Combat() and not ccR.Player.Is.Facing("target") and ccR.Target.Distance() >= 15)
		) 
		then
			if GetNumLootItems() < 1 then ClearTarget() end
		end

		if ccR.Target.Is.Attackable() 
		and ccR.Var("Auto_Target_Closest")
		then
			return 
		end

		vLootTime = nil
		local style = nil
		if ccR.Var("Auto_Target_In_Group") then style = "InGroup" end
		if ccR.Var("Auto_Target_Tapped_Only") then style = "InCombat" end
		--if ccR.Var("Auto_Target_Lowest_Health") then style = "LowestHealth" end
		if style == nil then style = "Any" end
		local wts = ccR.Var("WTS_AutoTarget")
		local los = ccR.Var("LoS_AutoTarget")
		local iT = ccR.Var("Auto_Target_Ignore_Tapped")

		local tmpUnit = nil
		local tmpDistance = 44
		
		local lowestHealth = 101
		if ccR.Target.Exists() then lowestHealth = ccR.Target.Health() end

		for x = 1, # ccR_Enemies_Within_44 do
			local obj = ccR_Enemies_Within_44[x]
			if ccR.Unit.Is.Attackable(obj)
			and (ccR.Player.Is.Facing(obj) or (ccR.Var("Use_Auto_Face") and ccR.Unit.Distance(obj, "player") <= 12 and ccR.Unit.Is.InCombat(obj)))
			and ccR.Unit.Distance(obj, "player") <= tmpDistance
			and (not wts or (wts and ccR.Unit.Is.VisibleOnScreen(obj)))
			and (not los or (los and ccR.Unit.Is.InLineOfSight(obj, "player")))
			and (not iT	
				or ccR.Unit.Is.Dummy(obj)	
				or (iT and (UnitIsTappedByPlayer(obj) 
							or not UnitIsTapped(obj) 
							or (UnitIsTapped(obj) and UnitIsTappedByAllThreatList(obj))
							or (select(8,GetInstanceInfo()) == 1148 and	UnitReaction("player", obj) <= 4) -- Proving Grounds
							)
					)
				)
			and not ccR.tblIgnoreNPC[ccR.Unit.NPCID(obj)]
			and not ccR.Unit.Is.Immune.To.All(obj)
			and not ccR.Sys.IgnoreNPCWithAura(obj)
			and not ccR.tblIgnoreCreatureType[UnitCreatureType(obj)] 
			and (not ccR.Var("Auto_Target_Ignore_Pets") or (ccR.Var("Auto_Target_Ignore_Pets") and not ccR.Unit.Is.APet(obj)))
			and not ccR.Unit.Is.CC(obj)
			then
				-- Different ways for Auto Target to choose it's target
				if 
				(
					style == "Any" or style == nil
					-- Only Enemies in combat with or is targetting player
					or (style == "InCombat" and (ccR.Unit.Is.TappedByPlayer(obj) or (ccR.Unit.TargetName(obj) == ccR.Player.Name())))
					-- Target anything but apply above in Group or Raid
					or (style == "InGroup" and (ccR.Player.Is.Solo() or (ccR.Unit.Is.TappedByPlayer(obj) or (ccR.Unit.TargetName(obj) == ccR.Player.Name()))))
				)
				and (not ccR.Var("Auto_Target_Lowest_Health") or (ccR.Var("Auto_Target_Lowest_Health") and (ccR.Unit.Health(obj) < lowestHealth)))
				then
					tmpUnit = obj
					tmpDistance = ccR.Unit.Distance(obj,"player")
					lowestHealth = ccR.Unit.Health(obj)
				end
				-- Ignore current target if Tapped
				if (style == "IgnoreTapped" and ccR.Unit.Is.Tapped(obj) and (not ccR.Unit.Is.TappedByPlayer(obj) or UnitIsTappedByAllThreatList(obj) == nil)) then tmpUnit = nil end
			end
		end

		if tmpUnit ~= nil then
			TargetUnit(tmpUnit)
			vLastAutoTarget = GetTime()
		end
	end,
}
setmetatable(ccR.Auto, ccR)